/*
 * Hosted Game: Powerball
 * D1st0rt, SSCE Hyperspace
 * License: MIT/X11
 * Created: 2009-05-20
 *
 * Race to score a certain number of goals
 */

///////////////////////////////////////////////////////////////////////
// Includes
///////////////////////////////////////////////////////////////////////

#include "stdlib.h"
#include "stdio.h"
#include "string.h"
#include "asss.h"
#include "hgcore.h"

///////////////////////////////////////////////////////////////////////
// Interfaces
///////////////////////////////////////////////////////////////////////

local Imodman *mm;
local Ilogman *lm;
local Ichat *chat;
local Igame *game;
local Icmdman *cmd;
local Iplayerdata *pd;
local Iarenaman *aman;
local Ihgcore *hgcore;
local Iballs *balls;
local Iconfig *config;

///////////////////////////////////////////////////////////////////////
// Defines/Types
///////////////////////////////////////////////////////////////////////
typedef struct pb_teamdata
{
	int Score;
}pb_teamdata;

typedef struct hg_pb_adata
{
	int Goals;
} hg_pb_adata;

///////////////////////////////////////////////////////////////////////
// Globals
///////////////////////////////////////////////////////////////////////
local int adkey;
local pthread_mutex_t globalmutex;

EXPORT const char info_hg_pb[] = "09.05.20 by D1st0rt <d1st0rter@gmail.com>";

///////////////////////////////////////////////////////////////////////
// Interface Prototypes
///////////////////////////////////////////////////////////////////////
local int OnPrepare(Arena *a, Player *host, const char *params);
local int OnStart(Arena *a, Player *host);
local void OnGameover(Arena *a, int how);
local void OnCleanup(Arena *a);
local void OnTeamCreate(Arena *a, HGTeam *team);
local void OnTeamDestroy(Arena *a, HGTeam *team);
local int SizeOfTeamData();
local void TeamInfoString(HGTeam *team, char *str, int buflen);
///////////////////////////////////////////////////////////////////////
// Prototypes
///////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////
// Callbacks
///////////////////////////////////////////////////////////////////////
void GoalScored(Arena *arena, Player *p, int bid, int x, int y);

///////////////////////////////////////////////////////////////////////
// Timers
///////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////
// Commands
///////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////
// Entry Point
///////////////////////////////////////////////////////////////////////
DEF_HG_INT("hg_pb");

EXPORT int MM_hg_pb(int action, Imodman *mm_, Arena *arena)
{
	if (action == MM_LOAD)
	{
	    // Global interfaces
		mm = mm_;
		chat    = mm->GetInterface(I_CHAT,       ALLARENAS);
		cmd     = mm->GetInterface(I_CMDMAN,     ALLARENAS);
		pd      = mm->GetInterface(I_PLAYERDATA, ALLARENAS);
		game    = mm->GetInterface(I_GAME,       ALLARENAS);
		lm      = mm->GetInterface(I_LOGMAN,     ALLARENAS);
		aman    = mm->GetInterface(I_ARENAMAN,   ALLARENAS);
		hgcore  = mm->GetInterface(I_HGCORE,     ALLARENAS);
		balls   = mm->GetInterface(I_BALLS,      ALLARENAS);
		config  = mm->GetInterface(I_CONFIG,     ALLARENAS);

		if (!chat ||
			!cmd ||
			!pd ||
			!aman ||
			!game ||
			!lm ||
			!aman ||
			!balls ||
			!config ||
			!hgcore)
			return MM_FAIL;

		// Data
		adkey = aman->AllocateArenaData(sizeof(hg_pb_adata));
        if (adkey == -1) return MM_FAIL;

        // Locking
		pthread_mutexattr_t attr;
		pthread_mutexattr_init(&attr);
		pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
		pthread_mutex_init(&globalmutex, &attr);
		pthread_mutexattr_destroy(&attr);

		return MM_OK;
	}
	else if (action == MM_UNLOAD)
	{
        // Locking
		pthread_mutex_destroy(&globalmutex);

		// Data
		aman->FreeArenaData(adkey);

        // Global interfaces
		mm->ReleaseInterface(config);
		mm->ReleaseInterface(balls);
		mm->ReleaseInterface(hgcore);
		mm->ReleaseInterface(lm);
		mm->ReleaseInterface(game);
		mm->ReleaseInterface(pd);
		mm->ReleaseInterface(cmd);
		mm->ReleaseInterface(chat);

        return MM_OK;
	}

	else if (action == MM_ATTACH)
	{
		// Interface registration
		mm->RegInterface(&hginterface, arena);
		hgcore->AttachGame(arena, I_HOSTEDGAME, "hg_pb");

		//Data
		hg_pb_adata *ad = P_ARENA_DATA(arena, adkey);
		ad->Goals = config->GetInt(arena->cfg, "Powerball", "GoalLimit", 5);

		//Attached interfaces

		//Callbacks
		mm->RegCallback(CB_GOAL, GoalScored, arena);

		//Timers

		//Commands


		return MM_OK;
	}
	else if (action == MM_DETACH)
	{
		//Data

		//Timers

		//Callbacks
		mm->UnregCallback(CB_GOAL, GoalScored, arena);

		//Commands

		// Interface registration
		if(!hgcore->DetachGame(arena))
		{
			return MM_FAIL;
		}

	    if (mm->UnregInterface(&hginterface, arena))
		{
			return MM_FAIL;
		}

		return MM_OK;
	}

	return MM_FAIL;
}

///////////////////////////////////////////////////////////////////////
// Interface Functions
///////////////////////////////////////////////////////////////////////
local int OnPrepare(Arena *a, Player *host, const char *params)
{
	hg_pb_adata *ad = P_ARENA_DATA(a, adkey);
	if(strlen(params))
	{
		int goals = atoi(params);
		if(goals)
		{
			ad->Goals = goals;
			chat->SendArenaMessage(a, "Powerball game about to begin: %d goal(s) to win!", goals);
		}
		else
		{
			chat->SendMessage(host, "Invalid number of goals specified");
			return 0;
		}
	}
	else
	{
		chat->SendArenaMessage(a, "Powerball game about to begin: %d goal(s) to win!", ad->Goals);
	}
	return 1;
}

local int OnStart(Arena *a, Player *host)
{
	chat->SendArenaSoundMessage(a, SOUND_GOAL, "Powerball game started!");
	return 1;
}

local void OnGameover(Arena *a, int how)
{
	if(how == HGR_NONE_REMAINING)
	{
		chat->SendArenaMessage(a, "Powerball game ended: no players left");
	}
	else if(how >= 0)
	{
		chat->SendArenaMessage(a, "Powerball game over! Team %d wins!", how);
	}
}

local void OnCleanup(Arena *a)
{
	//nothing required
}

local void OnTeamCreate(Arena *a, HGTeam *team)
{
	//nothing required
}

local void OnTeamDestroy(Arena *a, HGTeam *team)
{
	//nothing required
}

local int SizeOfTeamData()
{
	return sizeof(pb_teamdata);
}

local void TeamInfoString(HGTeam *team, char *str, int buflen)
{
	int offset = strlen(str);
	char *buf = (char *)(((char*)str)+offset);
	pb_teamdata *tdat = (pb_teamdata *)team->Data;
	snprintf(buf, buflen, " Goals: %d", tdat->Score);
}
///////////////////////////////////////////////////////////////////////
// Functions
///////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////
// Callbacks
///////////////////////////////////////////////////////////////////////
void GoalScored(Arena *a, Player *p, int bid, int x, int y)
{
	if(hgcore->GameStatus(a) == HGS_ACTIVE)
	{
		pb_teamdata *tdat = hgcore->GetTeamData(a, p->p_freq);
		hg_pb_adata *ad = P_ARENA_DATA(a, adkey);

		chat->SendArenaSoundMessage(a, SOUND_GOAL, "Goal scored for team %d by %s!", p->p_freq, p->name);
		tdat->Score++;
		if(tdat->Score >= ad->Goals)
		{
			hgcore->EndGame(a, p->p_freq);
		}
	}
}

///////////////////////////////////////////////////////////////////////
// Timers
///////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////
// Commands
///////////////////////////////////////////////////////////////////////

